﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web;
using OpenQuarters.WebQuarters.Core;
using OpenQuarters.WebQuarters.Utils;
using System.Xml.Serialization;
using System.IO;

namespace OpenQuarters.WebQuarters.Modules.Contact
{
    public class ContactModule : Module
    {
        [Serializable]
        public struct EmailCredentials
        {
            public string ToAddress;
            public string FromAddress;
            public string Subject;
            public string ReturnUrl;
        }

        public static Dictionary<string, string> AvailableForms
        {
            get
            {
                Dictionary<string, string> d = new Dictionary<string, string>();
                d.Add("OpenQuarters.WebQuarters.Modules.Contact,Resources.Default.tpl", "[Default]");

                foreach (string path in System.IO.Directory.GetFiles(Oracle.Request.MapPath("~/Forms/"), "*.tpl"))
                {
                    d.Add(System.IO.Path.GetFileNameWithoutExtension(path), System.IO.Path.GetFileName(path));
                }

                return d;
            }
        }

        private string form = "OpenQuarters.WebQuarters.Modules.Contact,Resources.Default.tpl";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.DropDown, OptionSource = "OpenQuarters.WebQuarters.Modules.Contact.ContactModule.AvailableForms")]
        public string Form
        {
            get { return form; }
            set { form = value; }
        }

        private string to_Address = "";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string To_Address {
            get { return to_Address; }
            set { to_Address = value; }
        }

        private string from_Address = "";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string From_Address
        {
            get { return from_Address; }
            set { from_Address = value; }
        }

        private string subject = "";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string Subject
        {
            get { return subject; }
            set { subject = value; }
        }

        private string introduction_Message = "Please use the form below to get in touch.";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string Introduction_Message
        {
            get { return introduction_Message; }
            set { introduction_Message = value; }
        }

        private string success_Message = "Thank you contacting us.";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string Success_Message
        {
            get { return success_Message; }
            set { success_Message = value; }
        }


        private bool use_JavaScript = true;

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.CheckBox)]
        public bool Use_JavaScript
        {
            get { return use_JavaScript; }
            set { use_JavaScript = value; }
        }

        public override void Initialise()
        {
            this.ModuleName = "Contact Form";
            this.ModuleDescription = "Places an contact form on the page";
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            var resp = JFormResponse<DefaultJFormClass>.Current;

            if (resp != null && resp.success)
            {
                this.Controls.AddLiteral("<span class=\"message\">" + this.success_Message + "</span>");
                JFormResponse<DefaultJFormClass>.Current = null;
            }
            else
            {
                if (!string.IsNullOrEmpty(this.introduction_Message))
                    this.Controls.AddLiteral("<span class=\"message\">" + this.introduction_Message + "</span>");

                EmailCredentials creds = new EmailCredentials();
                creds.ToAddress = this.to_Address;
                creds.FromAddress = this.from_Address;
                creds.Subject = this.subject;
                creds.ReturnUrl = Oracle.Request.Url.ToString();

                XmlSerializer Serializer = new XmlSerializer(typeof(EmailCredentials));
                StringWriter credsStream = new StringWriter();
                Serializer.Serialize(credsStream, creds);
                Utils.Encryption.SimpleAES aes = new Encryption.SimpleAES();
                string encyptedOptions = aes.EncryptToString(credsStream.ToString());

                if (form.IndexOf(",") == -1 && System.IO.File.Exists(Server.MapPath("~/Forms/" + form + ".tpl")))
                {
                    this.Controls.Add(new JForm(form, "/cms/modules/MethodHandler/OpenQuarters.WebQuarters.Modules.Contact,ContactModule,FormHandler", new { cmsEnv_options = encyptedOptions })
                    {
                        UseJavaScript = this.use_JavaScript,
                    });
                }
                else
                {
                    this.Controls.Add(new JForm(form, JForm.TemplateType.EmbeddedResource, "/cms/modules/MethodHandler/OpenQuarters.WebQuarters.Modules.Contact,ContactModule,FormHandler", new { cmsEnv_options = encyptedOptions })
                    {
                        UseJavaScript = this.use_JavaScript,
                    });
                }
            }
        }

        [Invokable]
        public static string FormHandler(HttpRequest request)
        {
            var resp = new JFormResponse<DefaultJFormClass>();

            if (request.Form["cmsEnv_options"] != null)
            {
            
                Utils.Encryption.SimpleAES aes = new Encryption.SimpleAES();
                XmlSerializer Serializer = new XmlSerializer(typeof(EmailCredentials));
                EmailCredentials creds = (EmailCredentials)Serializer.Deserialize(new StringReader(aes.DecryptString(request.Form["cmsEnv_options"])));

                StringBuilder sb = new StringBuilder();

                foreach (string field in request.Form.Keys)
                {
                    if (field.PadRight(7).Substring(0, 7) != "cmsEnv_")
                        sb.AppendLine(field + ": " + request.Form[field]);
                }

                bool sent = false;
                string emailClass = Oracle.GetSettings().ProviderSettings["Email"].Value;

                foreach (Type testClass in GeneralUtils.GetSubclassesOf(typeof(Core.IEmailProvider), true))
                {
                    if (testClass.FullName == emailClass)
                    {
                        try
                        {
                            ((IEmailProvider)Activator.CreateInstance(GeneralUtils.GetTypeByName(emailClass))).SendEmail(creds.ToAddress, creds.FromAddress, "", "", creds.Subject, sb.ToString(), false);
                            sent = true;
                        }
                        catch (System.Net.Mail.SmtpException ex)
                        {
                            resp.errorMessages.Add("General", new List<string>() { "There was an error sending the email, please try again later" });
                            EventLog.Add(EventLogPriority.M, "OpenQuarters.WebQuarters.Modules.Contact", "FormHandler", ex);
                        }
                        catch (Exception ex)
                        {
                            throw new ApplicationException("The Email Provider (" + emailClass + ") threw an exception.", ex);
                        }
                    }
                }

                //if (!sent)
                //    throw new ApplicationException("The Email Provider (" + emailClass + ") was not found");
            }

            JFormResponse<DefaultJFormClass>.Current = resp;

            return resp.ToJSON();
        }
    }
}
